<template>
  <div class="app-container">
    <el-card style="border: none;" shadow="never">
      <el-button
        type="primary"
        class="addrole"
        @click="handleAddRole"
      >新增角色</el-button>
      <el-table :data="rolesList" :header-cell-style="{background: '#f5f7fa'}" style="width: 100%; margin-top: 30px" border>
        <el-table-column align="center" label="标识">
          <template slot-scope="scope">
            {{ scope.row.name }}
          </template>
        </el-table-column>
        <el-table-column align="center" label="名称">
          <template slot-scope="scope">
            {{ scope.row.label_name }}
          </template>
        </el-table-column>
        <el-table-column align="center" label="角色说明">
          <template slot-scope="scope">
            {{ scope.row.description }}
          </template>
        </el-table-column>
        <el-table-column align="center" label="操作">
          <!-- <el-button type="primary">
            <i slot="icon" class="el-icon-edit"></i>
          </el-button> -->

          <template slot-scope="scope">
            <el-button
              icon="el-icon-user"
              size="small"
              type="text"
              @click="editRoleMember(scope.row)"
            />

            <el-button
              v-if="!isSuperAdmin(scope.row)"
              type="text"
              icon="el-icon-edit"
              size="small"
              @click="handleEdit(scope)"
            />
            <el-button
              v-if="scope.row.no_delete == null"
              type="text"
              size="small"
              icon="el-icon-delete"
              class="app-container-delete-btn"
              @click="handleDelete(scope)"
            />
          </template>
        </el-table-column>
      </el-table>
      <Pagination :total="total" :limit="params.paginate" @pagination="pagination" />
    </el-card>

    <DialogContent
      :visible.sync="dialogVisible"
      :close-on-click-modal="false"
      :title="dialogType === 'edit' ? '编辑角色' : '新增角色'"
      :custom-height="500"
    >
      <el-form
        ref="elForm"
        :model="role"
        :rules="rule"
        label-width="80px"
        label-position="left"
      >
        <el-form-item label="标识" prop="name">
          <el-input v-model="role.name" placeholder="标识">
            <template slot="append">_{{ defaultCompany.id }}</template>
          </el-input>
        </el-form-item>
        <el-form-item label="名字">
          <el-input v-model="role.label_name" placeholder="角色名" />
        </el-form-item>
        <el-form-item label="默认添加">
          <el-switch v-model="role.default" />
        </el-form-item>
        <el-form-item label="描述">
          <el-input
            v-model="role.description"
            :autosize="{ minRows: 2, maxRows: 4 }"
            type="textarea"
            placeholder="角色描述"
          />
        </el-form-item>
        <el-form-item label="菜单">
          <el-tree
            ref="tree"
            :data="routesData"
            :props="defaultProps"
            default-expand-all
            show-checkbox
            node-key="id"
            class="permission-tree"
          />
        </el-form-item>
        <el-form-item label="移动端菜单">
          <el-tree
            ref="wxTree"
            :data="routesWxData"
            :props="defaultProps"
            default-expand-all
            show-checkbox
            node-key="id"
            class="permission-tree"
          />
        </el-form-item>
      </el-form>
      <div style="text-align: right">
        <el-button type="danger" @click="dialogVisible = false">取消</el-button>
        <el-button type="primary" @click="confirmRole">确认</el-button>
      </div>
    </DialogContent>

    <RoleMemberEditor
      :role-i-d="roleMemberEditor.id"
      :fetch-role-members-fn="fetchRoleMembers"
      :fetch-employees-fn="fetchEmployeesFn"
      :save-fn="saveRoleMembers"
      :visible.sync="roleMemberEditor.visible"
      :members="roleMemberEditor.members"
      :employees="roleMemberEditor.employees"
    />

  </div>
</template>

<script>
import path from 'path'
import { deepClone } from '@/utils'
import Pagination from '@/components/Pagination/index.vue'
import {
  getRoutes,
  getRoles,
  addRole,
  deleteRole,
  updateRole,
  roleMembers
} from '@/api/role'
import { setRoleMembers } from '@/api/v2/role'
import { getAllUser } from '@/api/v2/personnel'
import { getMenu, getWxMenu } from '@/api/menu'
import { mapGetters } from 'vuex'
import { async } from 'q'
import DialogContent from '@/components/DialogContent/index.vue'
import RoleMemberEditor from '@/components/RoleMemberEditor/WithDialog.vue'
import { atLeast } from '@/utils/kris_utils'
const defaultRole = {
  key: '',
  name: '',
  description: '',
  routes: []
}

export default {
  components: {
    DialogContent,
    RoleMemberEditor,
    DialogContent,
    Pagination
  },
  data() {
    return {
      roleMemberEditor: {
        visible: false,
        id: null,
        members: [],
        employees: []
      },
      role: Object.assign({}, defaultRole),
      routes: [],
      wxRoutes: [],
      rolesList: [],
      dialogVisible: false,
      dialogType: 'new',
      checkStrictly: true,
      defaultProps: {
        children: 'children',
        label: 'title'
      },
      rule: {
        name: [{ required: true, message: '请输入角色标识', trigger: 'blur' }]
      },
      total: 0,
      params: {
        page: 1,
        paginate: 10
      }
    }
  },
  computed: {
    ...mapGetters(['defaultCompany']),
    routesData() {
      return this.routes
    },
    routesWxData() {
      return this.wxRoutes
    }
  },
  created() {
    // Mock: get all routes and roles list from server
    this.getRoutes()
    this.getRoles()
    this.fetchEmployeesFn()
  },
  methods: {
    isSuperAdmin(row) {
      const companyId = this.defaultCompany.id
      const roleName = row.name

      return roleName === `admin_${companyId}`
    },

    async saveRoleMembers(id, members) {
      const data = {
        roleId: id,
        userIds: JSON.stringify(members.map(member => member.id))
      }
      return members.length > 0 && setRoleMembers(data)
    },
    editRoleMember(row) {
      this.roleMemberEditor.id = row.id
      this.roleMemberEditor.visible = true
    },
    sleep(t) {
      return new Promise(r => setTimeout(r, t))
    },
    async fetchRoleMembers(id) {
      await this.sleep(200)
      const result = await roleMembers(id)
        .catch(e => {
          throw new Error(e.response.data.message ?? '获取角色下用户失败')
        })

      if (result.code !== 200) { throw new Error('获取角色下用户失败') }

      this.roleMemberEditor.members = result.data
        .filter(item => atLeast(item, ['username', 'phone', 'gender']))
        .map(item => {
          return {
            id: item.id,
            name: item.username,
            phone: item.phone,
            gender: item.gender
          }
        })
    },
    async fetchEmployeesFn(kw) {
      const result = await getAllUser({
        username: kw,
        type: 2
      })

      if (result.code !== 200) { throw new Error('获取失败') }

      this.roleMemberEditor.employees = result.data.map(item => {
        return {
          id: item.id,
          name: item.username,
          phone: item.phone,
          gender: item.gender
        }
      })
    },
    async getRoutes() {
      const res = await getMenu()
      const wxRes = await getWxMenu()
      // this.serviceRoutes = res.data
      this.routes = this.generateRoutes(res.data)

      this.wxRoutes = this.generateRoutes(wxRes.data)
    },
    async getRoles() {
      const { data, meta: { total, current_page }} = await getRoles(this.params)
      this.rolesList = data
      this.total = total
      this.params.page = current_page
    },
    handleCheckChange(data, checked, indeterminate) {},
    // Reshape the routes structure so that it looks the same as the sidebar
    generateRoutes(routes, basePath = '/') {
      const res = []

      for (let route of routes) {
        // skip some route
        if (route.hidden) {
          continue
        }

        const onlyOneShowingChild = this.onlyOneShowingChild(
          route.children,
          route
        )

        if (route.children && onlyOneShowingChild && !route.alwaysShow) {
          route = onlyOneShowingChild
        }
        const data = {
          path: path.resolve(basePath, route.path),
          title: route.meta && route.meta.title,
          id: route.id
        }
        // recursive child routes
        if (route.children) {
          data.children = this.generateRoutes(route.children, data.path)
        }
        res.push(data)
      }
      return res
    },
    generateArr(routes) {
      let data = []
      routes.forEach((route) => {
        if (!route.children) data.push(route)
        if (route.children) {
          const temp = this.generateArr(route.children)
          if (temp.length > 0) {
            data = [...data, ...temp]
          }
        }
      })
      return data
    },
    handleAddRole() {
      this.role = Object.assign({}, defaultRole)
      if (this.$refs.tree) {
        this.$refs.tree.setCheckedNodes([])
      }
      if (this.$refs.wxTree) {
        this.$refs.wxTree.setCheckedNodes([])
      }

      this.dialogType = 'new'
      this.dialogVisible = true
      this.$nextTick(() => {
        this.role = this.$options.data().role
        this.$refs.elForm.resetFields()
      })
    },
    handleEdit(scope) {
      console.log(scope.row, '-121212121---------------------------')
      this.dialogType = 'edit'
      this.dialogVisible = true
      this.checkStrictly = true
      this.role = deepClone(scope.row)
      console.log(this.role, '---------111111111')
      this.role.name = this.role.name.split('_')[0]
      this.role.default = this.role.default === 1
      this.$nextTick(() => {
        const routes = this.generateRoutes(this.role.web_menu)
        const wxRoutes = this.generateRoutes(this.role.wx_menu)
        this.$refs.tree.setCheckedNodes(this.generateArr(routes))
        this.$refs.wxTree.setCheckedNodes(this.generateArr(wxRoutes))
        // set checked state of a node not affects its father and child nodes
        this.checkStrictly = false
      })
    },
    handleDelete({ $index, row }) {
      this.$confirm('是否删除该角色', '删除角色', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      })
        .then(() => {
          this.deleteRoleFetch(row.id, $index)
        })
        .catch((err) => {
          console.error(err.response)
        })
    },

    async deleteRoleFetch(id, index) {
      try {
        const res = await deleteRole(id)
        if (res.status === 'fail') {
          return this.$message.error(res.message)
        }
        this.rolesList.splice(index, 1)
        this.$message({
          type: 'success',
          message: '删除成功！'
        })
      } catch (error) {
        this.$message.error(error?.response?.data?.message || '删除失败')
      }
    },

    generateTree(routes, basePath = '/', checkedKeys) {
      const res = []

      for (const route of routes) {
        const routePath = path.resolve(basePath, route.path)

        // recursive child routes
        if (route.children) {
          route.children = this.generateTree(
            route.children,
            routePath,
            checkedKeys
          )
        }

        if (
          checkedKeys.includes(routePath) ||
          (route.children && route.children.length >= 1)
        ) {
          res.push(route)
        }
      }
      return res
    },
    async confirmRole() {
      const isEdit = this.dialogType === 'edit'
      console.log(this.$refs.tree.getHalfCheckedNodes(), '321322--------------------------------')
      const checkedKeys = this.$refs.tree
        .getCheckedKeys()
        .concat(this.$refs.tree.getHalfCheckedKeys()) // 子节点与父节点拼接
      console.log(checkedKeys, '--------------------------------------------')
      const checkedKeysWx = this.$refs.wxTree
        .getCheckedKeys()
        .concat(this.$refs.wxTree.getHalfCheckedKeys()) // 子节点与父节点拼接

      this.role.menus = checkedKeys
      this.role.wx_menus = checkedKeysWx
      this.$refs.elForm.validate(async(res) => {
        if (res) {
          if (isEdit) {
            // 编辑
            try {
              await updateRole(this.role.id, this.role)
              this.dialogVisible = false
              this.$message.success('修改完成')
              this.getRoles()
            } catch (error) {
              this.$message.error(err.response.data.message)
            }
          } else {
            // 新增
            try {
              const { data } = await addRole(this.role)
              console.log(data)
              this.role.key = data.key
              this.dialogVisible = false
              this.$notify({
                title: '成功',
                dangerouslyUseHTMLString: true,
                message: '操作成功',
                type: 'success'
              })
              this.getRoles()
            } catch (err) {
              this.$message.error(err.response.data.message)
            }
          }
        } else {
          this.$message.error('请填写完整信息')
        }
      })

      const { description, key, name } = this.role
    },
    // reference: src/view/layout/components/Sidebar/SidebarItem.vue
    onlyOneShowingChild(children = [], parent) {
      let onlyOneChild = null
      const showingChildren = children.filter((item) => !item.hidden)

      // When there is only one child route, the child route is displayed by default
      // if (showingChildren.length === 1) {
      //   onlyOneChild = showingChildren[0]
      //   onlyOneChild.path = path.resolve(parent.path, onlyOneChild.path)
      //   return onlyOneChild
      // }

      // Show parent if there are no child route to display
      // if (showingChildren.length === 0) {
      onlyOneChild = { ...parent, path: '', noShowingChildren: true }
      return onlyOneChild
      // }

      return false
    },
    pagination(val) {
      this.params.page = val.page
      this.getRoles()
      console.log(val)
    }
  }
}
</script>

<style lang="scss" scoped>
.app-container {
  .permission-tree {
    margin-bottom: 30px;
  }
  .app-container-delete-btn{
    color: red;
  }
}
</style>
